package cn.iocoder.an.module.business.service.equipmentchecktype;

import cn.hutool.core.collection.CollUtil;
import cn.iocoder.an.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.an.framework.mybatis.core.query.MPJLambdaWrapperX;
import cn.iocoder.an.module.business.controller.admin.equipmentkeepsettingtype.vo.EquipmentKeepSettingTypeRespVO;
import cn.iocoder.an.module.business.controller.admin.equipmentmanage.vo.ImportRespVO;
import cn.iocoder.an.module.business.dal.dataobject.equipmentcheckconfig.EquipmentCheckConfigDO;
import cn.iocoder.an.module.business.dal.dataobject.equipmentkeepconfig.EquipmentKeepConfigDO;
import cn.iocoder.an.module.business.dal.dataobject.equipmentkeepsettingtype.EquipmentKeepSettingTypeDO;
import cn.iocoder.an.module.business.dal.dataobject.equipmentkeeptype.EquipmentKeepTypeDO;
import cn.iocoder.an.module.business.dal.dataobject.equipmentmanage.EquipmentManageDO;
import cn.iocoder.an.module.business.dal.mysql.equipmentcheckconfig.EquipmentCheckConfigMapper;
import cn.iocoder.an.module.business.dal.mysql.equipmentmanage.EquipmentManageMapper;
import io.micrometer.common.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

import cn.iocoder.an.module.business.controller.admin.equipmentchecktype.vo.*;
import cn.iocoder.an.module.business.dal.dataobject.equipmentchecktype.EquipmentCheckTypeDO;
import cn.iocoder.an.framework.common.pojo.PageResult;
import cn.iocoder.an.framework.common.pojo.PageParam;
import cn.iocoder.an.framework.common.util.object.BeanUtils;

import cn.iocoder.an.module.business.dal.mysql.equipmentchecktype.EquipmentCheckTypeMapper;

import static cn.iocoder.an.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.an.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.an.framework.common.util.collection.CollectionUtils.diffList;
import static cn.iocoder.an.module.business.enums.ErrorCodeConstants.*;

/**
 * 点检项设置 Service 实现类
 *
 * @author zzy
 */
@Service
@Validated
public class EquipmentCheckTypeServiceImpl implements EquipmentCheckTypeService {

    @Resource
    private EquipmentCheckTypeMapper equipmentCheckTypeMapper;

    @Resource
    private EquipmentCheckConfigMapper equipmentCheckConfigMapper;
    @Autowired
    private EquipmentManageMapper equipmentManageMapper;

    @Override
    public Long createEquipmentCheckType(EquipmentCheckTypeSaveReqVO createReqVO) {
        // 插入
        EquipmentCheckTypeDO equipmentCheckType = BeanUtils.toBean(createReqVO, EquipmentCheckTypeDO.class);
        equipmentCheckTypeMapper.insert(equipmentCheckType);

        // 返回
        return equipmentCheckType.getId();
    }

    @Override
    public void updateEquipmentCheckType(EquipmentCheckTypeSaveReqVO updateReqVO) {
        // 校验存在
        validateEquipmentCheckTypeExists(updateReqVO.getId());
        // 更新
        EquipmentCheckTypeDO updateObj = BeanUtils.toBean(updateReqVO, EquipmentCheckTypeDO.class);
        equipmentCheckTypeMapper.updateById(updateObj);
    }

    @Override
    public void deleteEquipmentCheckType(Long id) {
        // 校验存在
        validateEquipmentCheckTypeExists(id);
        // 删除
        equipmentCheckTypeMapper.deleteById(id);
    }

    @Override
    public void deleteEquipmentCheckTypeListByIds(List<Long> ids) {
        // 删除
        equipmentCheckTypeMapper.deleteByIds(ids);
    }


    private void validateEquipmentCheckTypeExists(Long id) {
        if (equipmentCheckTypeMapper.selectById(id) == null) {
            throw exception(EQUIPMENT_CHECK_TYPE_NOT_EXISTS);
        }
    }

    @Override
    public EquipmentCheckTypeDO getEquipmentCheckType(Long id) {
        return equipmentCheckTypeMapper.selectById(id);
    }

    @Override
    public PageResult<EquipmentCheckTypeDO> getEquipmentCheckTypePage(EquipmentCheckTypePageReqVO pageReqVO) {
        return equipmentCheckTypeMapper.selectPage(pageReqVO);
    }

    @Override
    public ImportRespVO importList(List<EquipmentCheckTypeImportExcelVO> list, boolean isUpdateSupport) {
        // 1.1 参数校验
        if (CollUtil.isEmpty(list)) {
            throw exception(IMPORT_EQUIPMENT_MANAGE_NOT_EXISTS);
        }

        //2.记录成功或失败记录
        ImportRespVO respVO = ImportRespVO.builder().insertNameList(new ArrayList<>())
                .updateNameList(new ArrayList<>()).failureMap(new LinkedHashMap<>()).build();

        AtomicInteger count = new AtomicInteger(1);
        list.forEach(equipment -> {
            count.incrementAndGet();//记录行号

            // 2.1.2 校验名称
            if (StringUtils.isEmpty(equipment.getName())) {
                respVO.getFailureMap().put("第" + count + "行数据", "点检项名称不能为空!");
                return;
            }

            // 2.1.3 校验状态
            if (equipment.getStatus() == null) {
                respVO.getFailureMap().put("第" + count + "行数据", "状态不能为空!");
                return;
            }

            equipmentCheckTypeMapper.insert(BeanUtils.toBean(equipment, EquipmentCheckTypeDO.class));
            respVO.getInsertNameList().add(equipment.getName());
        });
        return respVO;
    }

    @Override
    public Map<String, List<EquipmentCheckTypeRespVO>> getEquipmentCheckTypeMapList(EquipmentCheckTypePageReqVO reqVO) {
        Map<String, List<EquipmentCheckTypeRespVO>> map = new HashMap<>();
        map.put("bind", new ArrayList<>());
        map.put("unbound", new ArrayList<>());
        //类型ID或者设备ID
        Long targetId = reqVO.getTargetId();
        //按类型(1)还是按设备(2)
        Integer configType = reqVO.getType();

        if (targetId == null || configType == null) {
            throw exception(EQUIPMENT_CHECK_TYPE_NOT_EXISTS);
        }

        //1.获取符合条件的 点检项ID
        List<Long> ids = equipmentCheckConfigMapper.selectObjs(
                        new LambdaQueryWrapperX<EquipmentCheckConfigDO>()
                                .select(EquipmentCheckConfigDO::getCheckTypeId)
                                .eq(EquipmentCheckConfigDO::getConfigType, configType)
                                .eq(EquipmentCheckConfigDO::getTargetId, targetId)
                ).stream()
                .map(obj -> (Long) obj)
                .collect(Collectors.toList());


        if (ids.isEmpty()) {
            ids.add(0L);//防止为空报错
        }

        // 2.已绑定的
        MPJLambdaWrapperX<EquipmentCheckTypeDO> bindWrapper = new MPJLambdaWrapperX<>();
        bindWrapper.in(EquipmentCheckTypeDO::getId, ids);
        List<EquipmentCheckTypeDO> bindList = equipmentCheckTypeMapper.selectList(bindWrapper);
        List<EquipmentCheckTypeRespVO> bindBean = BeanUtils.toBean(bindList, EquipmentCheckTypeRespVO.class);
        map.put("bind", bindBean);

        //3.未绑定的
        MPJLambdaWrapperX<EquipmentCheckTypeDO> unboundWrapper = new MPJLambdaWrapperX<>();
        unboundWrapper.notIn(EquipmentKeepSettingTypeDO::getId, ids);
        unboundWrapper.eq(EquipmentCheckTypeDO::getStatus, 1);
        List<EquipmentCheckTypeDO> unboundList = equipmentCheckTypeMapper.selectList(unboundWrapper);
        List<EquipmentCheckTypeRespVO> unboundBean = BeanUtils.toBean(unboundList, EquipmentCheckTypeRespVO.class);
        map.put("unbound", unboundBean);
        return map;

    }

    @Override
    public Map<String, List<EquipmentCheckTypeRespVO>> checkMapList(EquipmentCheckTypePageReqVO reqVO) {
        Map<String, List<EquipmentCheckTypeRespVO>> map = new HashMap<>();
        map.put("bind", new ArrayList<>());
        map.put("unbound", new ArrayList<>());
        //类型ID或者设备ID
        Long targetId = reqVO.getTargetId();
        //按类型(1)还是按设备(2)
        Integer configType = reqVO.getType();

        if (targetId == null || configType == null) {
            throw exception(EQUIPMENT_CHECK_TYPE_NOT_EXISTS);
        }

        //1.获取符合条件的 点检项ID
        List<Long> ids = equipmentCheckConfigMapper.selectObjs(
                        new LambdaQueryWrapperX<EquipmentCheckConfigDO>()
                                .select(EquipmentCheckConfigDO::getCheckTypeId)
                                .eq(EquipmentCheckConfigDO::getConfigType, configType)
                                .eq(EquipmentCheckConfigDO::getTargetId, targetId)
                ).stream()
                .map(obj -> (Long) obj)
                .collect(Collectors.toList());


        if (ids.isEmpty()) {
          //按照设备的分类取一次
            EquipmentManageDO equipmentManageDO = equipmentManageMapper.selectById(targetId);
            Long equipmentClassify = equipmentManageDO.getEquipmentClassify();
            ids = equipmentCheckConfigMapper.selectObjs(
                            new LambdaQueryWrapperX<EquipmentCheckConfigDO>()
                                    .select(EquipmentCheckConfigDO::getCheckTypeId)
                                    .eq(EquipmentCheckConfigDO::getConfigType, 1)
                                    .eq(EquipmentCheckConfigDO::getTargetId, equipmentClassify)
                    ).stream()
                    .map(obj -> (Long) obj)
                    .collect(Collectors.toList());
        }

        if (ids.isEmpty()) {
            ids.add(0L);
        }

        // 2.已绑定的
        MPJLambdaWrapperX<EquipmentCheckTypeDO> bindWrapper = new MPJLambdaWrapperX<>();
        bindWrapper.in(EquipmentCheckTypeDO::getId, ids);
        List<EquipmentCheckTypeDO> bindList = equipmentCheckTypeMapper.selectList(bindWrapper);
        List<EquipmentCheckTypeRespVO> bindBean = BeanUtils.toBean(bindList, EquipmentCheckTypeRespVO.class);
        map.put("bind", bindBean);

        //3.未绑定的
        MPJLambdaWrapperX<EquipmentCheckTypeDO> unboundWrapper = new MPJLambdaWrapperX<>();
        unboundWrapper.notIn(EquipmentKeepSettingTypeDO::getId, ids);
        unboundWrapper.eq(EquipmentCheckTypeDO::getStatus, 1);
        List<EquipmentCheckTypeDO> unboundList = equipmentCheckTypeMapper.selectList(unboundWrapper);
        List<EquipmentCheckTypeRespVO> unboundBean = BeanUtils.toBean(unboundList, EquipmentCheckTypeRespVO.class);
        map.put("unbound", unboundBean);
        return map;
    }

}